#include "motor_control.h"
#include "servo_control.h"
#include "ch32v30x.h"
#include "math.h"
#include "debug.h"
#include "oled.h"
#include  "bmp.h"
#include "water.h"
#include "adcx.h"
#include "SOUND.h"
#include "FMQ.h"
#include "dht11.h"
#include "hx711.h"

u8 temp;//温度变量
u8 humi;//湿度变量
u16 value;//水位变量
float shuiwei;
int Sound_Level;

int w;
float weight;
int32_t reset;
u8 buff[30];
float Weights=0.578;  //578g
int32_t Weights_578=8454967;  //578g
// GPIO初始化函数
void Relay_GPIO_Config(void) {
    GPIO_InitTypeDef GPIO_InitStructure;

    // 使能GPIOC时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

    // 配置PC1引脚
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; // PC1
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    //设置低电平（继电器关断）
    GPIO_ResetBits(GPIOC, GPIO_Pin_1);
}

// 继电器控制函数
void Relay_Control(uint8_t state) {
    if(state == 1) {
        // 打开继电器（闭合）
        GPIO_SetBits(GPIOC, GPIO_Pin_1);  // 输出高电平
        Delay_Ms(2000);
        Delay_Ms(2000);
        Delay_Ms(2000);


    } else {
        // 关闭继电器（断开）
        GPIO_ResetBits(GPIOC, GPIO_Pin_1); // 输出低电平
    }
}


// 全局控制变量
volatile struct {
    uint8_t motor_speed;
    uint8_t motor_direction;
    float servo_angle;
} ctrl_params = {
    .motor_speed = 0,
    .motor_direction = MOTOR_FORWARD,
    .servo_angle = 0.0f
};

// TIM2中断处理函数（电机控制）
void TIM2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void TIM2_IRQHandler(void) {
    if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {

        uint8_t speed = ctrl_params.motor_speed;
        uint8_t dir = ctrl_params.motor_direction;

        // 更新电机PWM
        TIM_SetCompare1(TIM2, (uint16_t)((uint32_t)speed * PWM_PERIOD / 100));

        // 设置方向
        if(dir == MOTOR_FORWARD) {
            GPIO_ResetBits(AIN1_GPIO_PORT, AIN1_GPIO_PIN);
            GPIO_SetBits(AIN2_GPIO_PORT, AIN2_GPIO_PIN);
        } else {
            GPIO_SetBits(AIN1_GPIO_PORT, AIN1_GPIO_PIN);
            GPIO_ResetBits(AIN2_GPIO_PORT, AIN2_GPIO_PIN);
        }

        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
    }
}

// TIM1中断处理函数（舵机控制）
void TIM1_UP_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void TIM1_UP_IRQHandler(void) {
    if(TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET) {

        float angle = ctrl_params.servo_angle;

        // 更新舵机PWM
        uint16_t pulse_width = DS3120_MIN_US +
                            (uint16_t)((angle *
                                       (DS3120_MAX_US - DS3120_MIN_US)) / SERVO_MAX_ANGLE);
        TIM_SetCompare1(TIM1, pulse_width);

        TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
    }
}

// 初始化中断系统
void NVIC_Configuration(void) {
    NVIC_InitTypeDef NVIC_InitStructure;

    // TIM2中断配置（电机）10kHz
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // TIM1中断配置（舵机）50Hz
    NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // 启用定时器中断
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
    TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
}

// 真正的同步设置函数
void SetSyncMotion(uint8_t speed, uint8_t dir, float angle) {
    // 临界区开始
    __disable_irq();  // 关闭全局中断

    //同时更新所有参数
    ctrl_params.motor_speed = speed;
    ctrl_params.motor_direction = dir;
    ctrl_params.servo_angle = angle;

    __enable_irq();   // 恢复全局中断
}


// 串口2初始化
void UART2_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

    // TX(PA2)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // RX(PA3)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
    USART_Init(USART2, &USART_InitStructure);
    USART_Cmd(USART2, ENABLE);
}

// 串口2发送字符串
void UART2_SendString(char* str) {
    while (*str) {
        USART_SendData(USART2, *str++);
        while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
    }
}


int main(void) {
    /*================ 系统级初始化 ================*/
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  // 中断优先级分组配置
    SystemInit();                                    // 系统时钟初始化
    SystemCoreClockUpdate();                         // 更新系统核心时钟
    Delay_Init();                                    // 延时函数初始化

    /*================ 外设初始化 ================*/
    // 电机控制模块
    Motor_GPIO_Init();     // 电机GPIO初始化
    Motor_PWM_Init();      // 电机PWM初始化
    SERVO_Init();          // 舵机初始化
    MotorB_Init();
    GPIO_SetBits(STBY_GPIO_PORT, STBY_GPIO_PIN);  // 启用电机驱动

    // 传感器模块
    SOUND_Init();      // 声音传感器
    WATER_Init();      // 水位传感器
    HX711_Init();      // 压力传感器
    DHT11_Init();      // 温湿度传感器
    mfq_Init();        // 蜂鸣器

    /*================ 通信模块初始化 ================*/
    USART_Printf_Init(115200);  // 调试串口(连接电脑)
    UART2_Init();               // 通信串口(连接ESP8266)
    Relay_GPIO_Config();
    /*================ 显示模块初始化 ================*/
    OLED_Init();             // OLED基础初始化
    OLED_ColorTurn(0);       // 设置正常显示模式
    OLED_DisplayTurn(0);     // 设置屏幕方向
    OLED_Clear();            // 清屏
    OLED_ShowPicture(0, 0, 128, 32, BMP2, 1);  // 显示界面图标

    // 显示状态信息
    OLED_ShowChinese(0, 16, 2, 16, 1);
    OLED_ShowChinese(16, 16, 3, 16, 1);
    OLED_ShowChar(32, 16, ':', 16, 1);
    OLED_ShowChinese(0, 32, 4, 16, 1);
    OLED_ShowChinese(16, 32, 3, 16, 1);
    OLED_ShowChar(32, 32, ':', 16, 1);
    OLED_ShowChinese(0, 48, 5, 16, 1);
    OLED_ShowChinese(16, 48, 6, 16, 1);
    OLED_ShowChar(32, 48, ':', 16, 1);
    OLED_Refresh();  // 刷新显示

    /*================ 系统状态初始化 ================*/
    Delay_Ms(100);               // 稳定等待
    reset = HX711_GetData();     // 获取压力传感器基准值
    NVIC_Configuration();        //

    /*================ 系统启动通知 ================*/
    // 串口调试信息
    printf("Motor & Servo Control System Started\n");
    printf("Waiting for commands...\n");

    // 手机端指令说明
    UART2_SendString("Welcome to use the smart baby crib.\n");
    UART2_SendString("Swing mode 1\n");
    UART2_SendString("Swing mode 2\n");
    UART2_SendString("Swing mode 3\n");
    UART2_SendString("Swing mode 4\n");
    UART2_SendString("Swing mode 5\n");
    UART2_SendString("Swing mode 6\n");
    UART2_SendString("Swing mode 7\n");


    while(1) {

        value=WATER_GetData();
            printf("水位: %d\r\n",value);
            Delay_Ms(200);
            w = HX711_GetData();
            // 计算原始重量值
            float raw_weight = (float)(w - reset) * Weights / (float)(Weights_578 - reset);
            weight = roundf(raw_weight * 10) / 10.0f;
            sprintf((char*)buff, "%.1f", weight);
            printf("重量: %.1f kg\r\n", weight);
            // 1. 读取DHT11数据
                DHT11_Read_Data(&temp, &humi);
                Delay_Ms(1000);
                OLED_ShowNum(60, 16, temp, 2, 16, 1);
                OLED_ShowString(90, 16, "C", 16, 1);
                OLED_ShowNum(60, 32, humi, 2, 16, 1);
                OLED_ShowString(90, 32, "%", 16, 1);
                OLED_ShowString(90, 48, "Kg", 16, 1);
                //显示重量
                OLED_ShowString(60, 48, buff, 16, 1);
                // 5. 刷新屏幕
                OLED_Refresh();
                 Delay_Ms(200);
                 if(value>600)
                            {
                                fmq_on();
                                Delay_Ms(100);
                                fmq_off();
                                Delay_Ms(100);
                                fmq_on();
                                Delay_Ms(100);
                                fmq_off();
                                Delay_Ms(700);
                            }
                            else
                            {
                                fmq_off();
                            }


                 if(temp>30)
                                             {
                             fmq_on();
                             Delay_Ms(200);
                               fmq_off();
                               Delay_Ms(50);
                               fmq_on();
                                Delay_Ms(200);
                                       fmq_off();
                                       Delay_Ms(50);
                                           MotorB_Control(MOTOR_FORWARD, 50);
                                             }
                                             else
                                             {
                                                 fmq_off();
                                                 MotorB_Brake();
                                             }


                 Sound_Level = SOUND_Get();

                       if(Sound_Level == 1)
                       {
                           Relay_Control(1); // 音乐播放
                                  Delay_Ms(1000);
                                  for(uint8_t speed = 0; speed <= 100; speed += 5)
                                  {
                                                                         MotorA_Control(MOTOR_FORWARD, speed);
                                                                         Delay_Ms(50);
                                                                     }

                       }
                       else
                       {
                           Relay_Control(0); // PC1输出高电平，继电器关闭
                                  Delay_Ms(300);

                       }
                 // 处理串口2（手机）命令
                        if(USART_GetFlagStatus(USART2, USART_FLAG_RXNE) != RESET) {
                            char ch = USART_ReceiveData(USART2);
                            printf("Phone cmd: %c\n", ch);
                            switch(ch) {
                                case '1':
                                    for(uint8_t speed = 0; speed <= 100; speed += 2) {

                                                                                SetSyncMotion(speed, MOTOR_FORWARD, (float)speed * 0.9f);
                                                                                Delay_Ms(50);
                                                                            }
                                    UART2_SendString("Swing mode 1 OK\n");
                                    break;
                                case '2':

                                                                               for(uint8_t speed = 100; speed > 0; speed -= 2) {

                                                                                   SetSyncMotion(speed, MOTOR_BACKWARD, 90.0f - (float)speed * 0.9f);
                                                                                   Delay_Ms(50);
                                                                               }
                                    UART2_SendString("Swing mode 2 OK\n");
                                    break;
                                case '3':                                  //
                                    printf("Swing mode 3\n");
                                    //  减速后退，舵机放下
                                                                   for(uint8_t speed = 80; speed > 0; speed -= 5) {
                                                                       SetSyncMotion(speed, MOTOR_BACKWARD, 72.0f - (float)speed * 0.9f);
                                                                       Delay_Ms(50);
                                                                   }

                                                                   SetSyncMotion(0, MOTOR_FORWARD, 45.0f);
                                                                   Delay_Ms(1000);

                                    UART2_SendString("Swing mode 3 OK\n");
                                    break;
                                case '4':
                                    printf("Swing mode 4\n");
                                 // 同步加速
                                           for(uint8_t speed = 0; speed <= 100; speed += 2) {

                                               SetSyncMotion(speed, MOTOR_FORWARD, (float)speed * 0.9f);
                                               Delay_Ms(50);
                                           }
                                          //同步反向
                                           for(uint8_t speed = 100; speed > 0; speed -= 2) {

                                               SetSyncMotion(speed, MOTOR_BACKWARD, 90.0f - (float)speed * 0.9f);
                                               Delay_Ms(50);
                                           }
                                    UART2_SendString("Swing mode 4 OK\n");
                                    break;
                                case '5':
                                    printf("Swing mode 5\n");
                                                  for(uint8_t speed = 0; speed <= 100; speed += 5) {
                                                      ctrl_params.motor_speed = speed;
                                                      ctrl_params.servo_angle = (float)speed * 0.9f;
                                                      Delay_Ms(50);
                                                  }
                                    UART2_SendString("Swing mode 5 OK\n");
                                    break;
                                case '6':
                                                                 printf("music on\n");
                                                                 Relay_Control(1); // 音乐播放



                                                                 UART2_SendString("music on\n");
                                                                 break;
                                case '7':
                                                                 printf("music off\n");
                                                                 Relay_Control(0); // 音乐播放
                                                                 UART2_SendString("music off\n");
                                                                 break;
                                default:
                                    printf("Unknown command: %c\n", ch);
                                    UART2_SendString("Input error. Please input again.\n");
                                    break;
                            }
                        }

    }
}
